govendor
是 go
的一个比较好用包版本管理工具。主要用来保证 go
项目在协同开发或发版部署时,保证部署安装的依赖包版本对当前项目是稳定可用的。
为什么要使用包版本管理工具
java
的 maven
,php
的 composer
,nodejs
的 npm
,python
的 requirement.txt
,golang
的 govendor
。
例1:你的项目依赖一个github.com/foo 1.0.0
的包,如果不使用包版本管理工具,他人在本地部署安装你的项目时,安装的包版本可能是最新的github.com/foo 2.0.0
,如果两个版本存在兼容问题,就会出现crashed
。
例2:使用go get
安装的项目依赖包的存放位置为$GOPATH/src
,即与你的项目路径同级,我们使用git
时就没办法管理这些依赖包,不能也不应该将它们也提交到git
仓库,如果提供一个包版本说明说,将说明书提交仓库,他人则根据此说明书安装依赖包。
为解决此问题,govendor
出现了,govendor
会将项目依赖的包版本记录到your_proj/vendor/vendor.json
中,后期将此文件提交至 git
仓库,则其他人 pull or clone
你的项目到本地后,即可使用 govendor
安装稳定的包依赖。
govendor 工作流
首先要部署好你的 go
环境,并将 $GOPATH/bin
路径加载到系统PATH
中。我们将体验一遍如何使用govendor
管理你的项目包版本,及如何安装他人的govendor
管理的go
项目(这点才是精华,很多博文都不提及,为什么版本管理,不就是为了能让程序在其他地方也能稳定运行嘛)。
安装govendor
go get -u -v github.com/kardianos/govendor
#运行 govendor 检测安装结果
govendor
如果能看到帮助提示信息,说明安装ok。
项目初始化
使用 govendor
初始化你的项目,将会在工程目录下自动创建 vendor
目录及 vendor/vendor.json
文件。如果是已有项目,也没关系,govendor
允许你在项目开发的任何阶段去使用它,它总能将你的项目包版本管理起来。
mkdir go_proj && cd go_proj
# init proj
govendor init
#查看目录结构
tree
.
└── vendor
└── vendor.json
1 directory, 1 file
安装&更新包
govendor fetch
我们可以通过 govendor fetch -v path@version
的方式将依赖包安装至 project/vendor
下,或对已有的包进行更新。相比 go get -u
,本命令可以灵活的指定版本,go get
只能在 GOMODULE
模式下,才能指定包版本(GO111MODULE=on 或 (GO111MODULE=auto && 非 GOPATH/src下)
)。
#安装在 $GOPATH/src 下 如果在 GOPATH 模式下无法指定版本
go get -u -v github.com/go-sql-driver/mysql
#安装在your_proj/vendor下 可以指定版本
govendor fetch -v github.com/go-sql-driver/mysql@master
govendor list & govendor add/update
govendor list
可以帮助我们查看项目中引入的包的状态,即哪些是没有纳入版本管理的外部包,哪些是纳入版本管理的包,哪些是标准包,哪些是本地包等。
govendor list
Status Types
+local (l) packages in your project 你自己在项目中定义的包
+external (e) referenced packages in GOPATH but not in current project 在 GOPATH/src 下的包
+vendor (v) packages in the vendor folder 在 project/vendor 下的包
+std (s) packages in the standard library 标准包 fmt/time/runtime 等
+excluded (x) external packages explicitly excluded from vendoring 排除的外部包
+unused (u) packages in the vendor folder, but unused 安装但没引用的包
+missing (m) referenced packages but not found 引用但没安装的包 缺失了
+program (p) package is a main package 含有 main 方法的包
+outside +external +missing
+all +all packages
govendor add
则是方便我们在任何时间将项目包纳入版本管理。比如我们前期一直使用或现在偶然使用go get
安装了一个项目的依赖包,此包是不会被记录在vendor/vendor.json
中的,即没有纳入版本管理,那该如何将其纳入呢?
# 使用 GOPATH 下的包添加至 vendor 中
govendor add path
# 将所有的外部包复制到 vendor 下
govendor add +e
# 使用 GOPATH 下的包更新 vendor 中的包
govendor update path
# 使用 GOPATH 下的包更新 vendor 中的包
govendor update +e
执行上方命令即可,这样项目依赖的包都纳入了版本管理。
提交git仓库
在提交源码至 git
仓库时,我们没有必要将依赖包源文件也一并提交至仓库,所以 .gitignore
的编排要加上如下规则:
# vi .gitignore
vendor/*
!vendor/vendor.json
即排除 vendor
下的除 vendor/vendor.json
外的所有文件(这些文件其实就是依赖包),将 vendor/vendor.json
提交至git
仓库即可。
安装/部署 govendor 项目
当我们从 git
仓库下载好 govendor
管理的 golang
项目时,需要安装好项目的包依赖,才可以正常的运行程序,类似 composer install
的作用,这里则是使用 govendor sync
。
这里使用我的一个 govendor
管理的基于 Gin
的 MVC
简易框架给大家演示一下:
cd $GOPATH/src && git clone git@github.com:sqrtcat/easy-gin.git && cd easy-gin
govendor sync
运行程序即可,简单!
$GOPATH:bin/pkg/src
bin
安装后的可执行文件(编译并安装)pkg
编译后的包文件(编译)src
包源文件
go get
命令首先会将包的源文件下载至 src
中,然后检测包是否存在 main
方法。如果存在,那包将会被编译安装,编译后的库文件存放在 pkg
中,编译后的可执行文件存放在 bin
中。比如下面的例子,easy_go
中存在 main
方法,则执行 go get
后你会在 bin
中看到 easy_go
可执行文件。
go get -v github.com/sqrtcat/easy_go
echo export PATH=$PATH:$GOPATH/bin >> /etc/profile
source /etc/profile
# 就可以执行刚才安装的命令了 go
easy_go
go get pkg = git clone pkg && go install pkg
go install pkg = go build pkg + 安装至 bin
go build pkg = 只编译 不安装 可执行文件不会安装到 bin 目录
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。